package hasthi.metamodel.resource;

import hasthi.common.HasthiException;
import hasthi.common.XmlBeanUtils;
import hasthi.common.HasthiException.FaultCode;
import hasthi.common.constants.WSDMConstants.SystemState;

import java.io.IOException;
import java.io.Reader;

import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;

import wsdm.mows.BusyStateDocument;
import wsdm.mows.CrashedStateDocument;
import wsdm.mows.IdleStateDocument;
import wsdm.mows.SaturatedStateDocument;
import wsdm.mows.StoppedStateDocument;
import wsdm.muws.StateTransitionDocument;
import wsdm.muws.StateTransitionType;
import wsdm.muws.StateType;

/**
 * <p>
 * Information model can only hold String values, and any Objects need to be
 * encoded/converted to a string to store in the information model. This class
 * acts as a extension point that allow different converters to be plugged in.
 * </p>
 * 
 * @author Srinath Perera (hperera@cs.indiana.edu)
 */
public class ValueConverter {
    public String convert(Object object) throws HasthiException {
        if (object == null) {
            return null;
        } else if (object instanceof String) {
            return (String) object;
        } else {
            try {
                if (object instanceof XmlObject) {
                    Reader staxreader = ((XmlObject) object).newReader();
                    XmlObject realObj = XmlObject.Factory.parse(staxreader);
                    staxreader.close();
                    if (realObj instanceof StateTransitionDocument) {
                        StateTransitionDocument transitionDocument = (StateTransitionDocument) realObj;
                        StateTransitionType stateTransition = transitionDocument
                                .getStateTransition();
                        SystemState previousState = xmlBeanState2localState(stateTransition
                                .getPreviousState());
                        SystemState enteredState = xmlBeanState2localState(stateTransition
                                .getEnteredState());
                        return previousState + "->" + enteredState;
                    } else if (realObj instanceof StateType) {
                        SystemState state = xmlBeanState2localState((StateType) realObj);
                        return state != null ? state.toString() : null;
                    } else if (realObj instanceof IdleStateDocument) {
                        SystemState state = xmlBeanState2localState(((IdleStateDocument) realObj)
                                .getIdleState());
                        return state != null ? state.toString() : null;
                    } else if (realObj instanceof BusyStateDocument) {
                        SystemState state = xmlBeanState2localState(((BusyStateDocument) realObj)
                                .getBusyState());
                        return state != null ? state.toString() : null;
                    } else if (realObj instanceof SaturatedStateDocument) {
                        SystemState state = xmlBeanState2localState(((SaturatedStateDocument) realObj)
                                .getSaturatedState());
                        return state != null ? state.toString() : null;
                    } else if (realObj instanceof StoppedStateDocument) {
                        SystemState state = xmlBeanState2localState(((StoppedStateDocument) realObj)
                                .getStoppedState());
                        return state != null ? state.toString() : null;
                    } else if (realObj instanceof CrashedStateDocument) {
                        SystemState state = xmlBeanState2localState(((CrashedStateDocument) realObj)
                                .getCrashedState());
                        return state != null ? state.toString() : null;
                    }
                    System.out.println("############ Unkown type" + object);
                }
            } catch (XmlException e) {
                throw new HasthiException(e, FaultCode.InternalServiceError);
            } catch (IOException e) {
                throw new HasthiException(e, FaultCode.InternalServiceError);
            }

            return object.toString();
        }
    }

    private SystemState xmlBeanState2localState(StateType state) throws HasthiException {
        String stateName = XmlBeanUtils.getElementName(state).getLocalPart();
        
        for(SystemState allowedState:SystemState.values()){
            if(allowedState.toString().equals(stateName)){
                return allowedState;
            }
        }
        throw new HasthiException("Unknow state "+stateName,FaultCode.InvaliedLocalArgumnet);
    }
}
